package config

import (
	"context"
	"fmt"
	"log"
	"os"

	"WHY_GIN/models"
	"gopkg.in/yaml.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"io"
)

// Config 应用全局配置结构
// 包含数据库连接配置、调试模式等设置
type Config struct {
	Database struct {
		DSN        string `yaml:"dsn"`        // 数据库连接字符串
		DebugMode  bool   `yaml:"debugMode"`  // 调试模式开关
		SQLLogMode bool   `yaml:"sqlLogMode"` // SQL日志记录开关
		AutoMigrate bool  `yaml:"autoMigrate"` // 是否自动迁移数据库表结构
	} `yaml:"database"`
	Binance struct {
		APIKey     string `yaml:"apiKey"`     // Binance API密钥
		SecretKey  string `yaml:"secretKey"`  // Binance Secret密钥
		UseTestnet bool   `yaml:"useTestnet"` // 是否使用测试网络
	} `yaml:"binance"`
}

var (
	DB  *gorm.DB   // 全局数据库实例
	Cfg Config     // 全局配置实例
)

// InitConfig 初始化应用配置
// 完成配置文件的加载解析和数据库连接初始化
func InitConfig() {
	loadConfigFile()
	initDatabase()
}

// loadConfigFile 加载并解析配置文件
func loadConfigFile() {
	// 读取配置文件（支持绝对路径和相对路径）
	configPath := getConfigPath()
	file, err := os.Open(configPath)
	if err != nil {
		log.Fatalf("[配置加载失败] 打开配置文件失败: %v | 路径: %s", err, configPath)
	}
	defer file.Close()

	// 读取配置文件内容
	byteValue, err := io.ReadAll(file)
	if err != nil {
		log.Fatalf("[配置加载失败] 读取文件内容失败: %v", err)
	}

	// 解析YAML配置
	if err := yaml.Unmarshal(byteValue, &Cfg); err != nil {
		log.Fatalf("[配置解析失败] YAML解析错误: %v", err)
	}
}

// getConfigPath 获取配置文件路径
func getConfigPath() string {
	// 优先尝试当前目录下的config目录
	if _, err := os.Stat("config/config.yaml"); err == nil {
		return "config/config.yaml"
	}
	// 次尝试上层目录的config目录
	if _, err := os.Stat("../config/config.yaml"); err == nil {
		return "../config/config.yaml"
	}
	return "config/config.yaml"
}

// initDatabase 初始化数据库连接
func initDatabase() {
	var err error
	gormConfig := &gorm.Config{}

	// 配置日志级别
	if Cfg.Database.DebugMode {
		gormConfig.Logger = logger.Default.LogMode(logger.Info)
	} else {
		gormConfig.Logger = logger.Default.LogMode(logger.Silent)
	}

	// 建立数据库连接
	DB, err = gorm.Open(mysql.Open(Cfg.Database.DSN), gormConfig)
	if err != nil {
		log.Fatalf("[数据库连接失败] 连接字符串: %s | 错误详情: %v", 
			Cfg.Database.DSN, err)
	}

	// 配置SQL日志回调（仅在调试模式和SQL日志模式同时开启时生效）
	if Cfg.Database.DebugMode && Cfg.Database.SQLLogMode {
		registerQueryLogger()
	}

	// 测试数据库连通性
	if err := testDatabaseConnection(); err != nil {
		log.Fatalf("[数据库连接测试失败] %v", err)
	}

	// 根据配置决定是否执行自动迁移数据库表结构
	if Cfg.Database.AutoMigrate {
		if err := autoMigrate(); err != nil {
			log.Fatalf("[数据库迁移失败] %v", err)
		}
	} else {
		log.Println("[INFO] 数据库自动迁移已禁用，跳过表结构迁移")
	}
}

// registerQueryLogger 注册SQL查询日志回调
func registerQueryLogger() {
	DB.Callback().Query().Register("gorm:query_logger", func(db *gorm.DB) {
		ctx := context.WithValue(db.Statement.Context, "gorm:query_logger", true)
		db.Logger.Info(ctx, fmt.Sprintf(
			"[SQL执行] %s | 参数: %v",
			db.Statement.SQL.String(),
			db.Statement.Vars,
		))
	})
}

// testDatabaseConnection 测试数据库连接
func testDatabaseConnection() error {
	sqlDB, err := DB.DB()
	if err != nil {
		return fmt.Errorf("获取数据库实例失败: %w", err)
	}
	return sqlDB.Ping()
}

// autoMigrate 自动迁移数据库表结构
// 只进行安全的表结构更新，不会删除现有数据
func autoMigrate() error {
	log.Println("[INFO] 开始数据库表结构迁移...")
	
	// 自动迁移所有模型（只会添加新字段或索引，不会删除现有数据）
	err := DB.AutoMigrate(
		&models.TradeRecord{},
		&models.User{}, // 如果有其他模型也可以在这里添加
	)
	if err != nil {
		return fmt.Errorf("数据库表结构迁移失败: %w", err)
	}

	log.Println("[SUCCESS] 数据库表结构迁移完成，现有数据已保留")
	return nil
}
